{{>licenseInfo}}
import { HttpHeaders, HttpParams, HttpParameterCodec } from '@angular/common/http';
import { CustomHttpParameterCodec } from './encoder';
import { {{configurationClassName}} } from './configuration';
import { OpenApiHttpParams, QueryParamStyle, concatHttpParamsObject} from './query.params';

export class BaseService {
    protected basePath = '{{{basePath}}}';
    public defaultHeaders = new HttpHeaders();
    public configuration: {{configurationClassName}};
    public encoder: HttpParameterCodec;

    constructor(basePath?: string|string[], configuration?: {{configurationClassName}}) {
        this.configuration = configuration || new {{configurationClassName}}();
        if (typeof this.configuration.basePath !== 'string') {
            const firstBasePath = Array.isArray(basePath) ? basePath[0] : undefined;
            if (firstBasePath != undefined) {
                basePath = firstBasePath;
            }

            if (typeof basePath !== 'string') {
                basePath = this.basePath;
            }
            this.configuration.basePath = basePath;
        }
        this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
    }

    protected canConsumeForm(consumes: string[]): boolean {
        return consumes.indexOf('multipart/form-data') !== -1;
    }

    protected addToHttpParams(httpParams: OpenApiHttpParams, key: string, value: any | null | undefined, paramStyle: QueryParamStyle, explode: boolean): OpenApiHttpParams {
        if (value === null || value === undefined) {
            return httpParams;
        }

        if (paramStyle === QueryParamStyle.DeepObject) {
            if (typeof value !== 'object') {
                throw Error(`An object must be provided for key ${key} as it is a deep object`);
            }

            return Object.keys(value as Record<string, any>).reduce(
                (hp, k) => hp.append(`${key}[${k}]`, value[k]),
                httpParams,
            );
        } else if (paramStyle === QueryParamStyle.Json) {
            return httpParams.append(key, JSON.stringify(value));
        } else {
            // Form-style, SpaceDelimited or PipeDelimited

            if (Object(value) !== value) {
                // If it is a primitive type, add its string representation
                return httpParams.append(key, value.toString());
            } else if (value instanceof Date) {
                return httpParams.append(key, value.toISOString());
            } else if (Array.isArray(value)) {
                // Otherwise, if it's an array, add each element.
                if (paramStyle === QueryParamStyle.Form) {
                    return httpParams.set(key, value, {explode: explode, delimiter: ','});
                } else if (paramStyle === QueryParamStyle.SpaceDelimited) {
                    return httpParams.set(key, value, {explode: explode, delimiter: ' '});
                } else {
                    // PipeDelimited
                    return httpParams.set(key, value, {explode: explode, delimiter: '|'});
                }
            } else {
                // Otherwise, if it's an object, add each field.
                if (paramStyle === QueryParamStyle.Form) {
                    if (explode) {
                        Object.keys(value).forEach(k => {
                            httpParams = this.addToHttpParams(httpParams, k, value[k], paramStyle, explode);
                        });
                        return httpParams;
                    } else {
                        return concatHttpParamsObject(httpParams, key, value, ',');
                    }
                } else if (paramStyle === QueryParamStyle.SpaceDelimited) {
                    return concatHttpParamsObject(httpParams, key, value, ' ');
                } else {
                    // PipeDelimited
                    return concatHttpParamsObject(httpParams, key, value, '|');
                }
            }
        }
    }
}
